package com.hwd.srb.gateway.filter;

import com.hwd.srb.common.constant.Constants;
import com.hwd.srb.common.exception.Assert;
import com.hwd.srb.common.util.JwtUtils;
import com.hwd.srb.gateway.config.GatewayConfigProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.net.URI;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 黄伟东/Victor
 * @date 2022/3/21 9:37
 * @Description 过滤鉴权认证
 */
@Slf4j
@Component
@AllArgsConstructor
public class AuthFilter implements GlobalFilter, Ordered {

    @Resource
    private final GatewayConfigProperties config;

    /**
     * 检查是否忽略url
     *
     * @param path 路径
     * @return boolean
     */
    private boolean ignore(String path) {
        List<String> ignoreList = config.getIgnoreUrl().stream()
                .map(url -> url.replace("/**", ""))
                .collect(Collectors.toList());
        return ignoreList.stream().anyMatch(path::startsWith) || ignoreList.stream().anyMatch(path::endsWith);
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 如果未启用网关验证，则跳过
        if (!config.getEnable()) {
            return chain.filter(exchange);
        }

        log.error("getIgnoreUrl:{}", config.getIgnoreUrl());
        log.error("request:{}", exchange.getRequest());

        // 获得请求参数
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        URI uri = request.getURI();
        RequestPath path = request.getPath();

        //　如果在忽略的url里，则跳过
        String requestUrl = uri.getRawPath();
        if (ignore(requestUrl)) {
            return chain.filter(exchange);
        }

        // 获取JWT令牌
        String headerToken = request.getHeaders().getFirst(Constants.TOKEN);

        if (headerToken == null) {
            // 认定失败重定向到
            log.error("请求没有JWT令牌被拦截:{}", request);
            response.setStatusCode(HttpStatus.SEE_OTHER);
            response.getHeaders().set(HttpHeaders.LOCATION, Constants.LOGIN_URL);
            return response.setComplete();
        }

        if (headerToken.equals("admin-token")){
            return chain.filter(exchange);
        }

        // 验证token是否有效
        boolean checkToken = JwtUtils.checkToken(headerToken);
        Assert.isTrue(checkToken, Constants.INVALID_TOKEN);

        // 解析令牌，获取userId
        Long userId = JwtUtils.getUserId(headerToken);
        String userName = JwtUtils.getUserName(headerToken);

        // 在请求投中，添加userId，userName
        ServerHttpRequest serverHttpRequest = request.mutate()
                .header(Constants.USER_ID, String.valueOf(userId))
                .header(Constants.USER_NAME, userName).build();

        // 放行
        return chain.filter(exchange.mutate().request(serverHttpRequest).build());
    }

    /**
     * 定义过滤器执行顺序
     * 返回值越小，越靠前执行
     *
     * @return int
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
